
package Network;

import java.io.IOException;
import javax.microedition.io.*;

import Math.*;
import Utilities.AlertDialog;

/* Start of 'Server' class */
public final class Server implements Runnable
{
  private ServerSocketConnection Serv;
  private Dictionary Cons;
  private Thread WaitConTh;
  /* 'Server' class constructor
   * ARGUMENTS:
   *   - port for listening
   *       int Port;
   * RETURNS: None.
   */
  public Server( int Port )
  {
    try
    {
      Serv = (ServerSocketConnection) Connector.open("socket://:" + Port);
    } catch (IOException ex)
    {
      AlertDialog.ShowError("Server create failed.", true);
      return;
    }
    WaitConTh = new Thread(this);
    Cons = new Dictionary();
  } /* End of 'Server' class constructor */

  /* Thread run function
   * ARGUMENTS: None.
   * RETURNS: None.
   */
  public final void run( )
  {
    Connection Con;
    while (true)
    {
      try
      {
        Con = new Connection((SocketConnection)Serv.acceptAndOpen());
        if (Handle_NewConnection(Con) == false)
          Con.Close();
        else
        {
          Con.SrvRef = this;
          Cons.Add(Long.toString(Con.GetIdent()), Con);
        }
      } catch (IOException ex)
      {
        return;
      }
    }
  } /* End of 'run' function */

  /* Handle new connection processing function
   * ARGUMENTS:
   *   - new connection
   *       Connection Con;
   * RETURNS:
   *   - 'true' if all is okey, 'false' - otherwice
   *       boolean;
   */
  public boolean Handle_NewConnection( Connection Con )
  {
    return true;
  } /* End of 'Handle_NewConnection' function */

  /* Close connection by identificator function
   * ARGUMENTS:
   *   - connection identificator
   *       int Ident;
   * RETURNS: None.
   */
  public final void CloseConnection( int Ident )
  {
    ((Connection)Cons.Get(Long.toString(Ident))).Close();
    Cons.Delete(Long.toString(Ident));
  } /* End of 'CloseConnection' function */

  /* Close all connection function
   * ARGUMENTS: None.
   * RETURNS: None.
   */
  public final void CloseAllConnections( )
  {
    for (int i = 0; i < Cons.Size(); i++)
      ((Connection)Cons.GetByPos(i)).Close();
  } /* End of 'CloseAllConnections' function */

  /* Get all connection identificators function
   * ARGUMENTS: None.
   * RETURNS:
   *   - connection identificators
   *       int[];
   */
  public final int[] GetAllConnectionIdents( )
  {
    String KeysStr[] = (String [])Cons.GetAllKeys();
    int Keys[] = new int[KeysStr.length];
    for (int i = 0; i < KeysStr.length; i++)
      Keys[i] = (int)Long.parseLong(KeysStr[i]);

    return Keys;
  } /* End of 'GetAllConnectionIdents' function */

  /* Send bytes to connection by identificator function
   * ARGUMENTS:
   *   - connection`s identificator
   *       int Ident;
   *   - byte array to sand
   *       byte Bytes[];
   *   - number of bytes to send
   *       int Num;
   */
  public final void SendBytesTo( int Ident, byte Bytes[], int Num )
  {
    Connection Con = (Connection)Cons.Get(Long.toString(Ident));
    if (Con == null)
    {
      return;
    }
    Con.SendBytes(Bytes, Num);
  } /* End of 'SendBytesTo' function */

  /* Send bytes to all connections function
   * ARGUMENTS:
   *   - bytes to send
   *       byte Bytes[];
   *   - number of bytes to send
   *       int Num;
   * RETURNS: None.
   */
  public final void SendBytesToAll( byte Bytes[], int Num )
  {
    for (int i = 0; i < Cons.Size(); i++)
      ((Connection)Cons.GetByPos(i)).SendBytes(Bytes, Num);
  } /* End of 'SendBytesToAll' function */

  /* Get bytes from connection function
   * ARGUMENTS:
   *   - connection identificator
   *       int Ident;
   *   - number of bytes to get
   *       int Num;
   * RETURNS:
   *   - byte array gotten
   *       byte[];
   */
  public final byte[] GetBytesFrom( int Ident, int Num )
  {
    Connection Con = (Connection)Cons.Get(Long.toString(Ident));
    if (Con == null)
    {
      return null;
    }
    return Con.GetBytes(Num);
  } /* End of 'GetBytesFrom' function */

} /* End of 'Server' class */
